package com.bjbn.service.impl;

import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import com.bjbn.entity.BridgeInfo;
import com.bjbn.service.BridgeInfoService;
import lombok.extern.slf4j.Slf4j;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 廊桥信息服务实现类
 */
@Slf4j
@Service
public class BridgeInfoServiceImpl implements BridgeInfoService {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    private static final String INDEX_NAME = "bridge_info";

    @Override
    public boolean createIndex(String indexName) {
        try {
            boolean exists = elasticsearchClient.indices().exists(
                ExistsRequest.of(e -> e.index(indexName))
            ).value();

            if (!exists) {
                CreateIndexRequest createIndexRequest = CreateIndexRequest.of(
                    builder -> builder.index(indexName)
                );
                elasticsearchClient.indices().create(createIndexRequest);
                log.info("成功创建索引: {}", indexName);
            } else {
                log.info("索引已存在: {}", indexName);
            }
            return true;
        } catch (IOException e) {
            log.error("创建索引失败: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean deleteIndex(String indexName) {
        try {
            DeleteIndexRequest deleteIndexRequest = DeleteIndexRequest.of(
                builder -> builder.index(indexName)
            );
            elasticsearchClient.indices().delete(deleteIndexRequest);
            log.info("成功删除索引: {}", indexName);
            return true;
        } catch (IOException e) {
            log.error("删除索引失败: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean saveBridgeInfo(BridgeInfo data) {
        try {
            // 始终生成新的UUID，确保历史数据保存
            String uuid = UUID.randomUUID().toString();
            data.setId(uuid);
            
            // 设置保存时间，便于历史数据管理
            if (data.getBnCreateTime() == null) {
                data.setBnCreateTime(java.time.LocalDateTime.now());
            }

            elasticsearchClient.index(i -> i
                    .index(INDEX_NAME)
                    .id(uuid)
                    .document(data));

            log.info("成功保存廊桥信息到ES，ID: {}, 设备名称：{}, 保存时间：{}", 
                    uuid, data.getDeviceName(), data.getBnCreateTime());
            return true;
        } catch (Exception e) {
            log.error("保存廊桥信息到ES失败，设备名称：{}", data.getDeviceName(), e);
            return false;
        }
    }

    @Override
    public boolean saveBridgeInfoBatch(List<BridgeInfo> dataList) {
        if (dataList == null || dataList.isEmpty()) {
            return true;
        }

        try {
            BulkRequest.Builder br = new BulkRequest.Builder();
            java.time.LocalDateTime now = java.time.LocalDateTime.now();

            for (BridgeInfo data : dataList) {
                // 为每个文档生成唯一的UUID，确保历史数据保存
                String uuid = UUID.randomUUID().toString();
                data.setId(uuid);
                
                // 设置保存时间，便于历史数据管理
                if (data.getBnCreateTime() == null) {
                    data.setBnCreateTime(now);
                }

                br.operations(op -> op
                        .index(idx -> idx
                                .index(INDEX_NAME)
                                .id(uuid)
                                .document(data)));
            }

            BulkResponse result = elasticsearchClient.bulk(br.build());

            if (result.errors()) {
                log.error("批量保存廊桥信息到ES失败，存在错误");
                return false;
            }

            log.info("成功批量保存{}条廊桥信息到ES，每个文档都使用唯一UUID，保存时间：{}", 
                    dataList.size(), now);
            return true;
        } catch (Exception e) {
            log.error("批量保存廊桥信息到ES失败", e);
            return false;
        }
    }

    @Override
    public BridgeInfo findById(String id) {
        try {
            co.elastic.clients.elasticsearch.core.GetResponse<BridgeInfo> response = elasticsearchClient.get(
                g -> g.index(INDEX_NAME).id(id),
                BridgeInfo.class
            );

            if (response.found()) {
                return response.source();
            }
            return null;
        } catch (IOException e) {
            log.error("根据ID查询失败: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public List<BridgeInfo> findByDeviceNameContaining(String deviceName) {
        List<BridgeInfo> result = new ArrayList<>();

        try {
            SearchResponse<BridgeInfo> response = elasticsearchClient.search(s -> s
                    .index(INDEX_NAME)
                    .query(q -> q
                            .match(m -> m
                                    .field("deviceName")
                                    .query(deviceName)
                            ))
                    .size(1000), BridgeInfo.class);

            for (Hit<BridgeInfo> hit : response.hits().hits()) {
                result.add(hit.source());
            }

            log.info("查询廊桥信息成功，设备名称：{}，返回{}条记录", deviceName, result.size());
        } catch (Exception e) {
            log.error("查询廊桥信息失败，设备名称：{}", deviceName, e);
        }

        return result;
    }

    @Override
    public List<BridgeInfo> findByBrand(String brand) {
        List<BridgeInfo> result = new ArrayList<>();

        try {
            SearchResponse<BridgeInfo> response = elasticsearchClient.search(s -> s
                    .index(INDEX_NAME)
                    .query(q -> q
                            .match(m -> m
                                    .field("brand")
                                    .query(brand)
                            ))
                    .size(1000), BridgeInfo.class);

            for (Hit<BridgeInfo> hit : response.hits().hits()) {
                result.add(hit.source());
            }

            log.info("查询廊桥信息成功，厂家：{}，返回{}条记录", brand, result.size());
        } catch (Exception e) {
            log.error("查询廊桥信息失败，厂家：{}", brand, e);
        }

        return result;
    }

    @Override
    public List<BridgeInfo> findByArea(String area) {
        List<BridgeInfo> result = new ArrayList<>();

        try {
            SearchResponse<BridgeInfo> response = elasticsearchClient.search(s -> s
                    .index(INDEX_NAME)
                    .query(q -> q
                            .match(m -> m
                                    .field("area")
                                    .query(area)
                            ))
                    .size(1000), BridgeInfo.class);

            for (Hit<BridgeInfo> hit : response.hits().hits()) {
                result.add(hit.source());
            }

            log.info("查询廊桥信息成功，区域：{}，返回{}条记录", area, result.size());
        } catch (Exception e) {
            log.error("查询廊桥信息失败，区域：{}", area, e);
        }

        return result;
    }

    @Override
    public List<BridgeInfo> findByDeviceGroup(String deviceGroup) {
        List<BridgeInfo> result = new ArrayList<>();

        try {
            SearchResponse<BridgeInfo> response = elasticsearchClient.search(s -> s
                    .index(INDEX_NAME)
                    .query(q -> q
                            .match(m -> m
                                    .field("deviceGroup")
                                    .query(deviceGroup)
                            ))
                    .size(1000), BridgeInfo.class);

            for (Hit<BridgeInfo> hit : response.hits().hits()) {
                result.add(hit.source());
            }

            log.info("查询廊桥信息成功，设备组：{}，返回{}条记录", deviceGroup, result.size());
        } catch (Exception e) {
            log.error("查询廊桥信息失败，设备组：{}", deviceGroup, e);
        }

        return result;
    }

    @Override
    public List<BridgeInfo> findBySta(String sta) {
        List<BridgeInfo> result = new ArrayList<>();

        try {
            SearchResponse<BridgeInfo> response = elasticsearchClient.search(s -> s
                    .index(INDEX_NAME)
                    .query(q -> q
                            .match(m -> m
                                    .field("sta")
                                    .query(sta)
                            ))
                    .size(1000), BridgeInfo.class);

            for (Hit<BridgeInfo> hit : response.hits().hits()) {
                result.add(hit.source());
            }

            log.info("查询廊桥信息成功，设备状态：{}，返回{}条记录", sta, result.size());
        } catch (Exception e) {
            log.error("查询廊桥信息失败，设备状态：{}", sta, e);
        }

        return result;
    }

    @Override
    public List<BridgeInfo> findByIp(String ip) {
        List<BridgeInfo> result = new ArrayList<>();

        try {
            SearchResponse<BridgeInfo> response = elasticsearchClient.search(s -> s
                    .index(INDEX_NAME)
                    .query(q -> q
                            .match(m -> m
                                    .field("ip")
                                    .query(ip)
                            ))
                    .size(1000), BridgeInfo.class);

            for (Hit<BridgeInfo> hit : response.hits().hits()) {
                result.add(hit.source());
            }

            log.info("查询廊桥信息成功，IP地址：{}，返回{}条记录", ip, result.size());
        } catch (Exception e) {
            log.error("查询廊桥信息失败，IP地址：{}", ip, e);
        }

        return result;
    }

    @Override
    public List<BridgeInfo> findByDept(String dept) {
        List<BridgeInfo> result = new ArrayList<>();

        try {
            SearchResponse<BridgeInfo> response = elasticsearchClient.search(s -> s
                    .index(INDEX_NAME)
                    .query(q -> q
                            .match(m -> m
                                    .field("dept")
                                    .query(dept)
                            ))
                    .size(1000), BridgeInfo.class);

            for (Hit<BridgeInfo> hit : response.hits().hits()) {
                result.add(hit.source());
            }

            log.info("查询廊桥信息成功，责任部门：{}，返回{}条记录", dept, result.size());
        } catch (Exception e) {
            log.error("查询廊桥信息失败，责任部门：{}", dept, e);
        }

        return result;
    }

    @Override
    public long count() {
        try {
            co.elastic.clients.elasticsearch.core.CountResponse response = elasticsearchClient.count(
                c -> c.index(INDEX_NAME)
            );
            return response.count();
        } catch (IOException e) {
            log.error("统计文档总数失败: {}", e.getMessage(), e);
            return 0;
        }
    }

    @Override
    public boolean deleteAll() {
        try {
            deleteIndex(INDEX_NAME);
            createIndex(INDEX_NAME);
            log.info("成功清空索引: {}", INDEX_NAME);
            return true;
        } catch (Exception e) {
            log.error("清空索引失败: {}", e.getMessage(), e);
            return false;
        }
    }
}
